using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using System.Collections.Generic;
using Temp.Controller;
using Temp.Model;
using Temp.View;
using Microsoft.Xna.Framework.Input;
using Temp.NLG;
using Temp.Planner2;
using Temp.Minigame.Minigame1;
using Temp.Minigame.MiniGame2;
using Temp.Minigame.Minigame3;

namespace Temp
{
    /// <summary>
    /// This is the main type our game
    /// </summary>
    public class AlexGame : Game
    {
        GraphicsDeviceManager _graphics;
        SpriteBatch _spriteBatch;

        /** things in a Place **/
        List<Item> items;
        List<Character> npcs;
        List<Item> listInventory;

        int worldnum;
        List<Place> places;
        Texture2D[] placesImg;
        Texture2D currentPlaceImage;
       
        List<string> activityLog;
        
        /**Planner**/
        EventPlanner eventPlanner;
        StoryPlanner storyPlanner;
        PeerPlanner peerPlanner;

        /**Controller Variables**/
        PlaceController pCtr;
        ItemController itemCtr;
        ObjectController objCtr;
        CharacterController charCtr;
        
        /** View classes **/
        ItemView itemView;
        NPCView npcView;
        DialogueView dialogueV;
        Peer alex;
        Main mainView;
        DescriptorView descView;
        ComicStripDrawer comicDrawer;

        /** Flags **/
        public bool peerCanWalk { get; set; }
        public bool drawAlexWorld { get; set; }
        public bool inMinigame1 { get; set; }
        public bool inMinigame2 { get; set; }
        public bool inMinigame3 { get; set; }

        private bool startMiniGame2 = false;  
        /** Mini Games **/
        Game1 g;
        Game2 g2;    
        Game3 g3;


        /// <summary>
        /// Constructor class for AlexGame
        /// </summary>
        public AlexGame()
        {
            _graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
            
        }

        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        /// 
        protected override void Initialize()
        {
            // TODO: Add your initialization logic here
            mainView = new Main();
            worldnum = 2;
            activityLog = new List<string>();

            pCtr = new PlaceController();
            itemCtr = new ItemController();
            objCtr = new ObjectController();
            charCtr = new CharacterController();

            places = pCtr.getPlaces();
            placesImg = new Texture2D[places.Count];
            npcs = charCtr.getNPCs();
            items = itemCtr.getAllItems();
            listInventory = new List<Item>();

            storyPlanner = new StoryPlanner(activityLog, listInventory);

            comicDrawer = new ComicStripDrawer(this.Content, this);
            eventPlanner = new EventPlanner(items, listInventory, storyPlanner, this, comicDrawer, activityLog);
           
            storyPlanner.eventPlanner = eventPlanner;


            dialogueV = new DialogueView(eventPlanner, this);
            dialogueV.Initialize();

            eventPlanner.dv = dialogueV;
            storyPlanner.dv = dialogueV;

            peerPlanner = new PeerPlanner(storyPlanner, dialogueV, listInventory,activityLog);

            eventPlanner.peerPlanner = peerPlanner;

            itemView = new ItemView(items, dialogueV, storyPlanner.currentStoryNode, listInventory);
            itemView.Initialize();

            npcView = new NPCView(Content, npcs);
            //mainView = new Main();

            alex = new Peer(worldnum);
            alex.Initialize(listInventory, dialogueV, storyPlanner, this);
            alex.Npcs = npcs;
            alex.Items = items;
            descView = new DescriptorView();


            peerCanWalk = true;
            drawAlexWorld = true;

            initializeMiniGames();
            base.Initialize();

        }
       /// <summary>
       /// Initializes the mini-games used by the system
       /// </summary>
        private void initializeMiniGames()
        {
            g = new Game1(this.Content, this, storyPlanner);
            g.Initialize();

            g2 = new Game2(this.Content, this);
            g2.Initialize();

            g3 = new Game3(this.Content, this, storyPlanner);
            g3.Initialize();
        }


        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            _spriteBatch = new SpriteBatch(GraphicsDevice);

            mainView.LoadContent(Content);
            for (int i = 0; i < places.Count; i++)
            {
                placesImg[i] = Content.Load<Texture2D>(places[i].bg);
            }
            currentPlaceImage = placesImg[worldnum - 1];
             
            comicDrawer.LoadContent(); 
            itemView.LoadContent(Content);
            npcView.LoadContent(Content);
            descView.LoadContent(Content);

            dialogueV.LoadContent(Content);
            //dialogueV.LoadPeer(Content, "boy");
            alex.LoadContent(Content);
            //g.LoadPeer("boy");
            loadContentOfMiniGames();
            // TODO: use this.Content to load your game content here
        } 

        /// <summary>
        /// Loads the art assets for the minigames
        /// </summary>
        private void loadContentOfMiniGames()
        {
            g.LoadContent();  
            g2.LoadContent();
            g3.loadContent();
        }

        /// <summary>
        /// UnloadContent will be called once per game and is the place to unload
        /// all content.
        /// </summary>
        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }

        bool b = false;
        bool triggerStoryPlannerOnce = true;
        
        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        { 
            // TODO: Add your update logic here
            if (mainView.getPeer().Length > 0)
            {
                if (!b)
                {
                    dialogueV.LoadPeer(Content, mainView.getPeer());
                    alex.LoadPeer(Content, mainView.getPeer());
                    g.LoadPeer(mainView.getPeer()); 
                    
                    b = true;
                }
                if (b)
                {
                    if (triggerStoryPlannerOnce) {
                        storyPlanner.reEvaluateStory();
                        triggerStoryPlannerOnce = false;
                    }

                    if (gameTime.TotalGameTime.Minutes % 1 == 0 && gameTime.TotalGameTime.Seconds == 0)
                    {
                        storyPlanner.gameTime = gameTime.TotalGameTime.Minutes;
                        storyPlanner.reEvaluateStory();
                        //System.Diagnostics.Debug.WriteLine("game time min" + gameTime.TotalGameTime.Minutes);
                    }
                    if (drawAlexWorld)
                    {
                        alex.peerCanWalk = peerCanWalk;
                        if (!dialogueV.isShowing)
                        {
                            alex.Go();
                            alex.Update(gameTime);
                        }
                        else
                            alex.Stop();

                        alex.invShowing = itemView.showing;
                        descView.invShowing = itemView.showing;
                        /*
                         * Update items
                        */
                        items = storyPlanner.eventPlanner.itemList;
                        items = alex.Items;
                        itemView.Items = items;

                        if (alex.didChangePlace())                      // if you get an error here something's wrong with your Place table(more on the north, west, south, east)
                        {
                            worldnum = alex.CurPlace;
                            currentPlaceImage = placesImg[worldnum - 1];
                            alex.ChangePlace();
                            alex.Initialize(listInventory, dialogueV, storyPlanner, this);
                            descView.Show(false);
                            alex.setChangePlace(false);
                        }

                        itemView.Update(worldnum);
                        npcView.Update(worldnum);
                        descView.Update(gameTime);
                        dialogueV.Update();
                        descView.CurPlace = worldnum;
                        mainView.Update(gameTime);
                        peerPlanner.Update();
                        base.Update(gameTime);

                    }
                    else if (inMinigame1)
                    {
                        g.Update();

                    }
                    else if (inMinigame2)
                    {
                        g2.Update();
                    }
                    else if (inMinigame3) {
                        g3.Update();
                    }

                    else
                    {
                        comicDrawer.Update();
                    }
                }
            }
            else 
                mainView.Update(gameTime);
        }

        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.Black);
            _spriteBatch.Begin();
            // TODO: Add your drawing code here
             
            if (mainView.getPeer().Length > 0)
            {
                if (drawAlexWorld &&b)
                {
                    _spriteBatch.Draw(currentPlaceImage, new Vector2(0, 0), Color.White);

                    descView.Draw(_spriteBatch);
                    npcView.Draw(_spriteBatch);

                    base.Draw(gameTime);
                    itemView.DrawItems(_spriteBatch);
                    alex.Draw(_spriteBatch);
                    itemView.DrawInv(_spriteBatch);
                    dialogueV.Draw(_spriteBatch);

                }

                else if (inMinigame1)
                {
                    g.Draw(_spriteBatch);
                }
                else if (inMinigame2)
                {
                    if (!startMiniGame2)
                    {
                        //g2.game();
                        startMiniGame2 = true;
                    }
                    g2.Draw(_spriteBatch);
                }
                else if (inMinigame3) {
                    g3.Draw(_spriteBatch);
                }
                else
                {
                    comicDrawer.Draw(_spriteBatch);
                }
            }
            else
                mainView.Draw(_spriteBatch);
            _spriteBatch.End();
        }
          
    }
}
